//package com.shop.loan.util.pdf;
//
//
//import cn.hutool.core.codec.Base64;
//import com.itextpdf.text.*;
//import com.itextpdf.text.pdf.*;
//import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
//import com.itextpdf.text.pdf.security.*;
//import com.itextpdf.tool.xml.XMLWorkerHelper;
//import com.shop.loan.model.enums.ContractType;
//import com.shop.loan.oss.UCloudUtil;
//import com.shop.loan.sign.ESignUtil;
//import com.shop.loan.util.SealUtil;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//import sun.misc.BASE64Encoder;
//
//import javax.annotation.Resource;
//import java.io.*;
//import java.nio.charset.Charset;
//import java.security.*;
//import java.security.cert.Certificate;
//import java.util.*;
//import java.util.List;
//
//@Component
//public class PdfUtil {
//
//    @Value("${sys.file.path}")
//    private String sysFilePath;
//
//    @Resource
//    UCloudUtil uCloudUtil;
//
//    @Resource
//    SealUtil sealUtil;
//
//    @Resource
//    OrderSignByMybatisMapper orderSignByMybatisMapper;
//
//    /**
//     * 将文件转换为Base64编码
//     */
//    public static String fileToBase64(String path) {
//        try {
//            File file = new File(path);
//            FileInputStream inputFile = new FileInputStream(file);
//            byte[] buffer = new byte[(int) file.length()];
//            inputFile.read(buffer);
//            inputFile.close();
//            return new BASE64Encoder().encode(buffer);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//
////        String base64 = null;
////        InputStream in = null;
////        try {
////            File file = new File(path);
////            in = new FileInputStream(file);
////            byte[] bytes = new byte[(int) file.length()];
////            in.read(bytes);
////            base64 = Base64.encode(bytes);
////        } catch (Exception e) {
////            e.printStackTrace();
////        } finally {
////            if (in != null) {
////                try {
////                    in.close();
////                } catch (IOException e) {
////                    e.printStackTrace();
////                }
////            }
////        }
////        return base64;
//    }
//
//
//    /**
//     * 通过html生成文件
//     *
//     * @param htmlContent html格式内容
//     * @param file        输出文件file
//     */
//    private void createdPdfByItextHtml(String htmlContent, File file) {
//        InputStream inputStream = null;
//        FileOutputStream outputStream = null;
//        PdfWriter writer = null;
//        try {
//            // 1. 获取生成pdf的html内容
//            inputStream = new ByteArrayInputStream(htmlContent.getBytes("utf-8"));
//            outputStream = new FileOutputStream(file);
//            Document document = new Document();
//            writer = PdfWriter.getInstance(document, outputStream);
//            document.open();
//            // 2. 添加字体
////            XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
////            fontImp.register(getFontPath());
//            // 3. 设置编码
//            XMLWorkerHelper.getInstance().parseXHtml(writer, document, inputStream, Charset.forName("UTF-8"), new CustomXMLWorkerFontProvider());
//            // 4. 关闭,(不关闭则会生成无效pdf)
//            document.close();
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        } finally {
//            try {
//                if (writer != null) {
//                    writer.close();
//                }
//                if (outputStream != null) {
//                    outputStream.close();
//                }
//                if (inputStream != null) {
//                    inputStream.close();
//                }
//            } catch (IOException ex) {
//                ex.printStackTrace();
//            }
//        }
//    }
//
//    /**
//     * 字符串写入pdf文件
//     *
//     * @param content
//     * @param orderId
//     * @return
//     */
//    public String saveToPdf(String content, Long orderId, String type) {
//        String filePath = sysFilePath;
//        String fileName = orderId + "_" + type + ".pdf";
//        filePath = filePath + fileName;
////        createdPdfByItextHtml(content, new File(filePath));
//        return saveToPdfByFileName(content, filePath);
//    }
//
//
//    public String saveToPdfByFileName(String content, String filePath) {
//        createdPdfByItextHtml(content, new File(filePath));
//        return filePath;
//    }
//
//    /**
//     * 创建签章合同文件
//     *
//     * @param userName
//     * @param orderId
//     * @param pdfPath
//     * @param contractType
//     * @param date
//     * @return
//     */
//    public String createSignFile(String userName, Long orderId, String pdfPath, ContractType contractType, Date date) {
////        String pdfPath = saveToPdf(contractDetail, orderId, contractType.getType());
//        String pdfPathBySign = sysFilePath + "/" + orderId + "_" + contractType.getType() + "_sign_" + System.currentTimeMillis() + ".pdf";
//        String userPicPath = sysFilePath + "/pic/" + userName + ".png";
//        sealUtil.automaticGeneration(userName, userPicPath);
//
//        SignSetting signSetting = null;
//        if (ContractType.credit_query.getType().trim().equals(contractType.getType())) {
//            signSetting = getSignaturePositionBySignedUnit(pdfPath, ESignUtil.userKeyByCreditQuery);
//        } else if (ContractType.credit_apply.getType().trim().equals(contractType.getType())) {
//            signSetting = getSignaturePositionBySignedUnit(pdfPath, ESignUtil.userKeyByCreditApply);
//        } else if (ContractType.credit_pbcCreditAuthKey.getType().trim().equals(contractType.getType())
//                || ContractType.credit_userAuthProtocol.getType().trim().equals(contractType.getType())) {
//            signSetting = getSignaturePositionBySignedUnit(pdfPath, ESignUtil.pbcCreditAuthKey);
//        }
//        sign(pdfPath, pdfPathBySign, userPicPath, signSetting, date, 80);
//
//        return uCloudUtil.putFile(pdfPathBySign, null);
//    }
//
////    public void createSignFileByOrder(UserOrder userOrder) {
////        String pdfPath = null;
////        for (OrderContract orderContract : userOrder.getOrderContracts()) {
////            if (orderContract.getContract().getType() == 1) {
////                pdfPath = orderContract.getContractLocalPath();
////            }
////        }
//////        pdfPath = "/Users/ddc/Downloads/contract_587_1_1712731829564.pdf";
////        if (!StringUtils.hasLength(pdfPath)) {
////            return;
////        }
////
////        String jia = "甲方代表(盖章)：";
////        String yi = "乙方代表(签字)：";
////        String bing = "丙方代表(盖章)：";
////
////        String userPicPath = sysFilePath + "/pic/" + userOrder.getRentalUser().getName() + ".png";
////        sealUtil.automaticGeneration(userOrder.getRentalUser().getName(), userPicPath);
////
////        SignSetting signSetting_jia = getSignaturePositionBySignedUnit(pdfPath, jia);
////        signSetting_jia.setPosX(signSetting_jia.getPosX() + 50);
////        SignSetting signSetting_yi = getSignaturePositionBySignedUnit(pdfPath, yi);
////        signSetting_yi.setPosX(signSetting_yi.getPosX() + 50);
////        SignSetting signSetting_bing = getSignaturePositionBySignedUnit(pdfPath, bing);
////        signSetting_bing.setPosX(signSetting_bing.getPosX() + 50);
////
////        String pdfPathBySign_1 = sysFilePath + "/contract_" + userOrder.getId() + "_1_" + System.currentTimeMillis() + ".pdf";
////        sign(pdfPath, pdfPathBySign_1, userOrder.getBusiness().getRecordApplySignPic(), signSetting_jia, userOrder.getBusinessTime(), 150);
////        String pdfPathBySign_2 = sysFilePath + "/contract_" + userOrder.getId() + "_1_" + System.currentTimeMillis() + ".pdf";
////        sign(pdfPathBySign_1, pdfPathBySign_2, userPicPath, signSetting_yi, userOrder.getBusinessTime(), 80);
////        String pdfPathBySign_3 = sysFilePath + "/contract_" + userOrder.getId() + "_1_" + System.currentTimeMillis() + ".pdf";
////        sign(pdfPathBySign_2, pdfPathBySign_3, "/data/service/rental-sys/sign/bing.png", signSetting_bing, userOrder.getBusinessTime(), 150);
////
////        OrderSignByMybatis orderSignByMybatis = new OrderSignByMybatis();
////        orderSignByMybatis.setOrderId(userOrder.getId());
////        orderSignByMybatis.seteSignUrl("/" + uCloudUtil.putFile(pdfPathBySign_3, null));
////        orderSignByMybatisMapper.updateSignUrlByOrderType(orderSignByMybatis);
////    }
//
//
//    public String createSignFileByPic(String signPic, Long orderId, String pdfPath, ContractType contractType, Date date) {
//        String pdfPathBySign = sysFilePath + "/0仲裁申请书_" + orderId + "_" + System.currentTimeMillis() + ".pdf";
//        int picSize = 80;
//        SignSetting signSetting = null;
//        if (ContractType.record_apply.getType().trim().equals(contractType.getType())) {
//            //仲裁申请书
//            picSize = 150;
//            signSetting = getSignaturePositionBySignedUnit(pdfPath, "申请人：");
//        }
//
//        System.out.println(signSetting);
//
//        sign(pdfPath, pdfPathBySign, signPic, signSetting, date, picSize);
//
//        return uCloudUtil.putFile(pdfPathBySign, null);
//    }
//
//
//    /**
//     * 在已经生成的pdf上添加电子签章，生成新的pdf并将其输出出来
//     *
//     * @param srcPath     需要签章的pdf文件路径
//     * @param destPath    签完章的pdf文件路径
//     * @param chapterPath
//     * @throws GeneralSecurityException
//     * @throws IOException
//     * @throws DocumentException
//     */
//    public void sign(String srcPath, String destPath, String chapterPath, SignSetting signSetting, Date date, int picSize) {
//        String reason = "rental-sign";
//        String location = "rental-location";
//
//        InputStream src = null;
//        OutputStream dest = null;
//        InputStream p12Stream = null;
//        PdfReader reader = null;
//        PdfStamper stamper = null;
//        try {
//            src = new FileInputStream(srcPath);
//            dest = new FileOutputStream(destPath);
//            p12Stream = this.getClass().getClassLoader().getResourceAsStream("aaaa.p12");
//            char[] password = "rental".toCharArray();
//
//            //读取keystore ，获得私钥和证书链
//            KeyStore ks = KeyStore.getInstance("PKCS12");
//            ks.load(p12Stream, password);
//            String alias = (String) ks.aliases().nextElement();
//            PrivateKey pk = (PrivateKey) ks.getKey(alias, password);
//            Certificate[] chain = ks.getCertificateChain(alias);
//
//            //下边的步骤都是固定的，照着写就行了，没啥要解释的
//            // Creating the reader and the stamper，开始pdfreader
//            reader = new PdfReader(src);
//
//            //目标文件输出流
//            //创建签章工具PdfStamper ，最后一个boolean参数
//            //false的话，pdf文件只允许被签名一次，多次签名，最后一次有效
//            //true的话，pdf可以被追加签名，验签工具可以识别出每次签名之后文档是否被修改
//            stamper = PdfStamper.createSignature(reader, dest, '\0', null, true);
//            // 获取数字签章属性对象，设定数字签章的属性
//            PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
//            appearance.setReason(reason);
//            appearance.setLocation(location);
//            Calendar calendar = Calendar.getInstance();
//            calendar.setTime(date);
//            appearance.setSignDate(calendar);//签署时间
//
//            //设置签名的位置，页码，签名域名称，多次追加签名的时候，签名预名称不能一样
//            //签名的位置，是图章相对于pdf页面的位置坐标，原点为pdf页面左下角
//            //四个参数的分别是，图章左下角x，图章左下角y，图章右上角x，图章右上角y
//            int leftX = signSetting.getPosX() + 30;
//            int leftY = signSetting.getPosY();
//
//            int rightX = leftX + picSize;
//            int rightY = leftY - picSize;
//            appearance.setVisibleSignature(new Rectangle(leftX, leftY, rightX, rightY), signSetting.getPage(), "rental_" + signSetting.getPosY() + "_" + signSetting.getPosX());
//            //读取图章图片，这个image是itext包的image
//            Image image = Image.getInstance(chapterPath);
//            appearance.setSignatureGraphic(image);
//            appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
//            //设置图章的显示方式，如下选择的是只显示图章（还有其他的模式，可以图章和签名描述一同显示）
//            appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
//
//            // 这里的itext提供了2个用于签名的接口，可以自己实现，后边着重说这个实现
//            // 摘要算法
//            ExternalDigest digest = new BouncyCastleDigest();
//            // 签名算法
//            ExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, null);
//            // 调用itext签名方法完成pdf签章CryptoStandard.CMS 签名方式，建议采用这种
//            MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                if (src != null) {
//                    src.close();
//                }
//                if (dest != null) {
//                    dest.close();
//                }
//                if (p12Stream != null) {
//                    p12Stream.close();
//                }
//                if (reader != null) {
//                    reader.close();
//                }
//                if (stamper != null) {
//                    stamper.close();
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//
//    /**
//     * 根据落款单位获取该落款单位在PDF文件中的位置信息，用来进行电子签章
//     * Author:
//     * Date: 2022-08-24 14:32
//     *
//     * @param fileName PDF文件路径
//     * @param unitName 落款单位名称
//     * @return 电子签章位置信息
//     */
//    public SignSetting getSignaturePositionBySignedUnit(String fileName, String unitName) {
//        SignSetting rtnSetting = null;
//
//        PdfReader pdfReader = null;
//        try {
//            // 初始化PDF文件
//            pdfReader = new PdfReader(fileName);
//            // 获取PDF文件总页数
//            int pdfPage = pdfReader.getNumberOfPages();
//            // PDF 内容
//            PdfReaderContentParser parser = new PdfReaderContentParser(pdfReader);
//            // 从最后一页开始查找落款单位名称，找到后直接跳出循环
//
//            // region 获取KeyWordBean
//
//            // 根据落款单位定位
//            for (int i = pdfPage; i >= 1; i--) {
//                SignSetting finalSignSetting = null;
//                // PDF当前页文本处理
//                PdfRenderListener listener = new PdfRenderListener();
//                parser.processContent(i, listener);
//
//                // PDF 获取关键词所在位置信息
//                finalSignSetting = getKeyWordPosition(listener.getTextChunkRenderInfoList(), unitName);
//                if (finalSignSetting != null) {
//                    finalSignSetting.setPage(i);
//                    rtnSetting = finalSignSetting;
//                    break;
//                }
//            }
//            // 位置调整，章是从这里开始下方盖章，所以位置上移部分，可以盖在字的上面
//            if (rtnSetting != null) {
//                rtnSetting.setPosY(rtnSetting.getPosY() + 50);
//            }
//
//            // endregion
//
//            // 如果未找到，就把章盖到最后一页
//            if (rtnSetting == null) {
//                rtnSetting = new SignSetting();
//                rtnSetting.setPage(pdfPage);
//            }
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        } finally {
//            if (pdfReader != null) {
//                pdfReader.close();
//            }
//        }
//        return rtnSetting;
//    }
//
//    /**
//     * 获取关键词所在位置信息
//     *
//     * @param textChunkRenderInfoList 文本块信息
//     * @param keyWord                 关键词
//     * @return 关键词位置信息
//     */
//    private SignSetting getKeyWordPosition(List<TextChunkRenderInfo> textChunkRenderInfoList, String keyWord) {
//        SignSetting signSetting = null; // 返回盖章配置信息
//        TextChunkMatchResult matchResult = null; // 最终匹配结果
//
//        keyWord = keyWord.replace(" ", ""); // 去除中间空格
//        // 第一个匹配到的文本信息
//        TextChunkRenderInfo firstCharMatch = null;
//        // 第一个匹配到的文本位置信息
//        int firstMatchPos = 0;
//        // 第一个匹配到的字符长度信息
//        int firstMatchLength = 0;
//        // 已经匹配成功的字符长度
//        int matchLength = 0;
//        for (TextChunkRenderInfo renderInfo : textChunkRenderInfoList) {
//            int textStart = 1;
//            while (textStart <= renderInfo.getText().length()) {
//                int[] matchRes = renderInfo.getTextContainWordInfo(keyWord, textStart, matchLength + 1);
//                if (matchRes == null) {
//                    firstCharMatch = null;
//                    if (matchLength == 0) {
//                        break;
//                    }
//                    matchLength = 0;
//                    continue;
//                }
//                if (matchLength == 0) {
//                    firstCharMatch = renderInfo;
//                    firstMatchPos = matchRes[0];
//                    firstMatchLength = matchRes[1];
//                }
//                matchLength += matchRes[1];
//                if (matchLength >= keyWord.length()) { // 已经完全匹配成功
//                    // 初始化匹配结果
//                    matchResult = new TextChunkMatchResult();
//                    matchResult.setFirstMatchRenderInfo(firstCharMatch);
//                    matchResult.setFirstMatchLength(firstMatchLength);
//                    matchResult.setFirstMatchStartIndex(firstMatchPos - 1);
//                    matchResult.setLastMatchRenderInfo(renderInfo);
//
//                    firstCharMatch = null;
//                    firstMatchPos = 0;
//                    firstMatchLength = 0;
//                    matchLength = 0;
//                }
//                textStart = matchRes[0] + matchRes[1];
//            }
//        }
//        if (matchResult != null) { // 成功匹配到了最后一个
//            signSetting = new SignSetting();
//            float posX = matchResult.getFirstMatchRenderInfo().getMinX();
//            // 将左侧未匹配到的距离加上
//            posX = posX + matchResult.getFirstMatchRenderInfo().getWordWidth() * matchResult.getFirstMatchStartIndex();
//            signSetting.setPosX((int) posX);
//            signSetting.setPosY((int) matchResult.getFirstMatchRenderInfo().getMinY());
//        }
//        return signSetting;
//    }
//
//    /**
//     * 获取文件md5
//     *
//     * @param filePath
//     * @return
//     * @throws IOException
//     * @throws NoSuchAlgorithmException
//     */
//    public static String getMD5(String filePath) throws IOException, NoSuchAlgorithmException {
//        File file = new File(filePath);
//        FileInputStream fileInputStream = null;
//        MessageDigest MD5 = MessageDigest.getInstance("MD5");
//        fileInputStream = new FileInputStream(file);
//        byte[] buffer = new byte[8092];
//        int length;
//        while ((length = fileInputStream.read(buffer)) != -1) {
//            MD5.update(buffer, 0, length);
//        }
//        return Base64.encode(MD5.digest());
//    }
//
//}
